package com.lalameow.researchstation

import com.lalameow.researchstation.api.technology.CommandReward
import com.lalameow.researchstation.api.technology.FluidRequirement
import com.lalameow.researchstation.api.technology.FluidResource
import com.lalameow.researchstation.api.technology.ItemRequirement
import com.lalameow.researchstation.api.technology.ItemResource
import com.lalameow.researchstation.api.technology.ItemReward
import com.lalameow.researchstation.api.technology.PlayerStatRequirement
import com.lalameow.researchstation.api.technology.SingleTechnologyCriterion
import com.lalameow.researchstation.api.technology.StageReward
import com.lalameow.researchstation.api.technology.StatResource
import com.lalameow.researchstation.api.technology.TechnologyCriterion
import com.lalameow.researchstation.api.technology.TechnologyRequirement
import com.lalameow.researchstation.api.technology.TechnologyResource
import com.lalameow.researchstation.api.technology.TechnologyReward
import com.lalameow.researchstation.util.serialization.TextAsJsonStringSerializer
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.cbor.Cbor
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.contextual
import kotlinx.serialization.modules.plus
import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.modules.subclass
import net.minecraft.text.Text
import net.minecraft.text.TranslatableText
import net.silkmc.silk.core.serialization.serializers.ResourceLocationSerializer
import net.silkmc.silk.nbt.serialization.Nbt

val ResearchStation.MOD_ID: String
    get() = "research-station"
val ResearchStation.MOD_PREFIX: String
    get() = "research_station"

internal val ResearchStation.Nbt: Nbt
    get() = Nbt {}

@OptIn(ExperimentalSerializationApi::class)
internal val ResearchStation.Cbor: Cbor
    get() = Cbor {
        serializersModule = Nbt.serializersModule + SerializersModule {
            contextual(ResourceLocationSerializer)

            polymorphicDefaultSerializer(Text::class) { TextAsJsonStringSerializer }
            polymorphicDefaultDeserializer(Text::class) { TextAsJsonStringSerializer }

            polymorphic(TechnologyRequirement::class) {
                subclass(ItemRequirement::class)
                subclass(FluidRequirement::class)
                subclass(PlayerStatRequirement::class)
            }

            polymorphic(TechnologyCriterion::class) {
                subclass(SingleTechnologyCriterion::class)
            }

            polymorphic(TechnologyResource::class) {
                subclass(FluidResource::class)
                subclass(ItemResource::class)
                subclass(StatResource::class)
            }

            polymorphic(TechnologyReward::class) {
                subclass(CommandReward::class)
                subclass(ItemReward::class)
                subclass(StageReward::class)
            }
        }
    }

fun ResearchStation.translatable(key: String) = TranslatableText("$MOD_PREFIX.$key")
fun ResearchStation.translatable(key: String, vararg args: Any) = TranslatableText("$MOD_PREFIX.$key", args)
